import { getBaoCangParams, getBatchData, getBigTime, getDeleteDataParams, getSyncTimeByPosition, getZhiMaPositionParams, handelLSCWDirection, handleHistoryPositionTimeOld } from './../../util/index';
import { forwardRef, Inject, Injectable } from '@nestjs/common';
import {
  adminGate,
  countHPositionSY,
  formatError,
  formatPage,
  formatSearchTime,
  formatSuccess,
  gateRestClient,
  getSyncTime,
  getSyncUserParams,
  getUpdateHistoryTime,
  getZmKeys,
  handleSeatchTime,
  handlePositionLv,
  historyPositionRuKu,
  jingDuSum,
  orderAddHeyue,
  weiShiXianYingKui,
  ysxYingKui,
} from 'src/util';
import { SetLeverageDto } from './dto/setLeverage.dto';
import { handlePositionZhiYingSunData } from 'src/util/helper';
import { GateService } from '../gate/gate.service';
import { UserService } from '../user/user.service';
import { TongBuPosition } from '../tong-bu-position/entities/tong-bu-position.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Between, Repository } from 'typeorm';
import { Position } from './entities/position.entity';
import { TongBuPositionService } from '../tong-bu-position/tong-bu-position.service';
import { OrderService } from '../order/order.service';
const dayjs = require('dayjs');
@Injectable()
export class PositionsService {
  // constructor(private gateService: GateService) { }
  constructor(
    @InjectRepository(TongBuPosition)
    private readonly tongBuPositionRepository: Repository<TongBuPosition>,
    @InjectRepository(Position)
    private readonly positionRepository: Repository<Position>,
    private gateService: GateService,
    @Inject(forwardRef(() => UserService))
    private userService: UserService,
    private tongBuPositionService: TongBuPositionService,
    private orderService: OrderService,
  ) {}

  // 设置杠杆
  async setLeverage(setLeverageDto: SetLeverageDto) {
    const params: any = {
      settle: 'usdt',
      ...setLeverageDto,
    };
    const res: any = await gateRestClient.updateFuturesLeverage(params);
    return formatSuccess(res);
  }

  /*
  仓位列表
  传userids[]获取key, 和方向
  */
  async positions(e: any, isAdmin = false) {
    const params: any = {
      ...e,
      settle: 'usdt',
      holding: true, // 返回真实持仓
      limit: 100,
      offset: 0,
    };
    let newGate: any = false;
    // 1. api: 查用户的芝麻key，目前只查单用户
    const users = await getZmKeys(params?.userIds, this.userService);
    if (!users || users.length === 0) return formatSuccess([]);
    const userData = users[0];
    delete params?.userIds;
    newGate = adminGate(userData);
    const res = await newGate.getFuturesPositions(params);
    const arr: any = res.filter((item: any) => item.value !== '0')?.reverse();
    // 处理仓位的止盈损数据
    for (const item of arr) {
      const zhiYingParams = {
        status: 'open',
        contract: item?.contract,
        limit: 100,
        offset: 0,
      };
      // api: 处理仓位的止盈损数据
      const zhiyingRes: any = (await this.getZhiYingSun(zhiYingParams, newGate))?.data;
      const isZuoDuo = item?.size * userData?.direction > 0; // 是否做多
      item.zhiYingSunData = handlePositionZhiYingSunData(zhiyingRes, isZuoDuo);
      item.zhiYingSunYuanShiData = zhiyingRes; // 止盈止损原始数据
    }
    // 添加合约详情
    let list: any = arr;
    list = await orderAddHeyue(list, this.gateService);
    // 处理开仓均价、处理杠杆信息、未实现盈亏
    list.forEach((item: any, i) => {
      item.id = i + 1;
      item.price = item?.entry_price;
      item.leverInfo = handlePositionLv(item);
      item.baoZhengJin = Number(item?.leverage !== '0' ? item?.margin : item?.initial_margin);
      item.ysxYingKui = ysxYingKui(item, userData?.direction);
      item.weiShiXianYingKui = weiShiXianYingKui(item, userData?.direction);
      item.userId = userData?.id;
      item.userName = userData?.name;
      item.userDirection = userData?.direction;
    });
    return formatSuccess(list);
  }

  // 历史仓位-分页
  async historyPositionsFenYe(params: any, newGate, current = 1) {
    const pageSize = params?.limit;
    delete params?.userIds;
    let list = [];
    const res = await newGate.getFuturesPositionHistory(params);
    list = [...list, ...res];
    if (res?.length >= pageSize) {
      params.offset = current * pageSize;
      const _current = current + 1;
      const res2 = await this.historyPositionsFenYe(params, newGate, _current);
      list = [...list, ...res2];
      return list;
    } else {
      return list;
    }
  }

  // 历史仓位
  // params={from,to ,users}
  async historyPositions({ from, to, userIds }: any) {
    let newGate: any = false;
    const users = await getZmKeys(userIds, this.userService);
    if (!users || users.length === 0) return formatSuccess([]);
    const userData: any = users[0];
    // 获取查询时间范围
    const timeData = handleHistoryPositionTimeOld({ from, to, userCreateTime: userData?.create_time });
    newGate = adminGate(userData);
    // console.log('params: 历史仓位', timeData?.startTime, timeData?.endTime);
    const params = {
      from: timeData?.from,
      to: timeData?.to,
      settle: 'usdt',
      limit: 1000,
      offset: 0,
    };
    // console.log('params:历史仓位 ', params);
    const res = await this.historyPositionsFenYe(params, newGate);
    // 添加合约详情
    let list: any = res;
    list = await orderAddHeyue(list, this.gateService);
    // 处理开仓均价、处理杠杆信息
    list.forEach((item: any, i) => {
      item.id = i + 1;
      item.userData = userData;
      item.userId = userData?.id;
      item.userName = userData?.name;
      item.userDirection = userData?.direction;
      item.userZhiMaKey = userData?.key;
      item.userTongBuTime = userData?.tongBuTime;
      item.price = item.side === 'long' ? item?.short_price : item?.long_price;
      item.leverInfo = handlePositionLv(item);
      item.ysxYingKui = ysxYingKui(item, userData?.direction);
    });
    return formatSuccess(list);
  }

  // 止盈止损
  async zhiYingSun(e: any) {
    const params: any = {
      ...e,
      settle: 'usdt',
    };
    const res: any = await gateRestClient.submitFuturesPriceTriggeredOrder(params);
    return formatSuccess(res);
  }

  // 获取止盈止损列表
  async getZhiYingSun(e: any, newGate: any = false) {
    const params: any = {
      ...e,
      settle: 'usdt',
    };
    let res: any;
    if (!newGate) {
      res = await gateRestClient.getFuturesAutoOrders(params);
    } else {
      res = await newGate.getFuturesAutoOrders(params);
    }
    return formatSuccess(res);
  }

  // 删除止盈止损
  async deleteZhiYingSun(e: any) {
    const params: any = {
      ...e,
      settle: 'usdt',
    };
    const res: any = await gateRestClient.cancelFuturesPriceTriggeredOrder(params);
    return formatSuccess(res);
  }

  // 后台仓位列表
  async htPositions(params) {
    const ids = params?.userIds;
    if (!ids || ids?.length === 0) return formatError({ msg: '用户id不能为空' });
    const arr = ids.map((item) => this.positions({ userIds: [item] }));
    const res: any = await Promise.allSettled(arr);
    const list: any[] = [];
    res.map((item) => {
      if (item?.status === 'fulfilled') list.push(...item?.value?.data);
    });
    return formatSuccess(list);
  }

  // 后台历史仓位列表
  async htLSPositions(params) {
    return await this.historyPositions(params);
  }

  // 定时同步芝麻的历史仓位 ,可以选同步的日期(时分秒)
  async tongBuHistoryPositions({ date = null }) {
    console.log('==== 开始同步历史仓位，date', date);
    const tongBuDate = date; // 同步日期
    // 1. 获取用户列表，筛选有芝麻的用户
    const users = (await this.userService.findAll({}))?.data?.list?.filter((item) => item?.zhima);
    const userIds = users.map((item) => item.id);
    console.log('== 同步：获取用户-end');
    // 2. 获取历史仓位
    const positionParams = getUpdateHistoryTime(users, tongBuDate);
    // console.log('参数：查询时间 ', positionParams);
    const getPositions = positionParams.map(({ userIds, from, to }) => this.historyPositions({ userIds, from, to }));
    const cangWeiRes = await Promise.allSettled(getPositions);
    const aYuanShiArr = cangWeiRes.map((item: any) => item?.value?.data || []);
    let allList = [];
    aYuanShiArr.map((item) => {
      allList = [...allList, ...item];
    });
    console.log('== 同步: 获取历史仓位-end');
    // 3. 将历史仓位入库
    await historyPositionRuKu(allList, this.positionRepository);
    console.log('===将历史仓位入库完成 ==');
    // 4. 记录同步信息
    const jiLuRes = await this.jiLuTongBuInfo(aYuanShiArr, users, positionParams);
    const tongBuJiLu = jiLuRes?.tongBuJiLu;
    console.log('记录同步信息 完成 ==');
    // 5. 计算芝麻的总盈亏，更新用户的同步时间和芝麻的总盈亏
    const syncUserParams = getSyncUserParams(tongBuJiLu, tongBuDate);
    console.log('syncUserParams: 更新用户', syncUserParams[0]);
    const syncUserRes = await Promise.allSettled(syncUserParams.map((item) => this.userService.edit(item)));
    // const syncUserRes = {};
    console.log('==== 同步结束');
    return formatSuccess({
      users,
      aYuanShiArr,
      List: allList,
      listMap: jiLuRes?.listMap,
      tongBuJiLu: jiLuRes?.tongBuJiLu,
      totalUser: userIds.length,
      total: allList.length,
      syncUserParams,
      syncUserRes,
    });
  }

  // 记录同步信息
  async jiLuTongBuInfo(data, users, positionParams) {
    const timeObj = getSyncTimeByPosition(positionParams);
    // 1.处理有平仓数据的用户
    const listMap = data
      .filter((item) => item.length > 0)
      .map((item: any) => {
        const user = item[0];
        // 1 计算盈亏
        const yingKuiBenCi = countHPositionSY(item);
        return {
          userId: user?.userId,
          userName: user?.userName,
          direction: user?.userDirection,
          key: user?.userZhiMaKey,
          pingCangNum: item.length,
          ...timeObj[user?.userId],
          yingKuiZhiQian: '0',
          yingKuiBenCi,
          yingKuiAll: '0',
          allMoneyZhiQian: 0,
          allMoney: 0,
          positions: item,
        };
      });
    // 2.添加没有平仓数据的用户
    const tongBuJiLu = [];
    users.map((user, i) => {
      const data = listMap.find((item) => item.userId === user.id);
      const yingKuiZhiQian = user?.yingKui;
      const allMoneyZhiQian = user?.allMoney;
      if (data) {
        data.yingKuiZhiQian = yingKuiZhiQian;
        data.yingKuiAll = jingDuSum([yingKuiZhiQian, data?.yingKuiBenCi]);
        data.allMoneyZhiQian = allMoneyZhiQian;
        data.allMoney = jingDuSum([allMoneyZhiQian, data?.yingKuiBenCi]);
        tongBuJiLu.push(data);
      } else {
        tongBuJiLu.push({
          userId: user.id,
          userName: user.name,
          direction: user.direction,
          key: user?.zhima?.key,
          pingCangNum: 0,
          ...timeObj[user?.id],
          yingKuiZhiQian: yingKuiZhiQian,
          yingKuiBenCi: '0',
          yingKuiAll: yingKuiZhiQian,
          allMoneyZhiQian: allMoneyZhiQian,
          allMoney: allMoneyZhiQian,
          positions: [],
        });
      }
    });
    // 入库
    const ruKu = tongBuJiLu.map((item) => {
      const params = { ...item };
      delete params?.positions;
      return this.tongBuPositionRepository.save(params);
    });
    const val: any = await Promise.allSettled(ruKu); // api
    const res = val.every((item) => item.status === 'fulfilled');
    // const res = {};
    return {
      res,
      listMap,
      tongBuJiLu,
    };
  }

  // 获取历史仓位-黑洞
  // 因为要插入最新的历史数据放弃分页,justMyData只要我们数据的数据，
  async myHistoryPosition({ userIds, startTime = null, endTime = null, justMyData = false }) {
    const userId = userIds[0];
    // 处理时间问题
    // 1. api: 查用户的芝麻key，目前只查单用户
    const users = await getZmKeys(userIds, this.userService);
    if (!users || users.length === 0) return formatSuccess([]);
    const userData = users[0];
    const { startTime: _startTime, endTime: _endTime } = handleSeatchTime({ startTime, endTime, userCreateTime: userData?.create_time });
    // 查询条件
    const where: any = {};
    if (userId) where.userId = userId;
    where.pingCangTime = Between(_startTime, _endTime);
    const arr = await this.positionRepository.find({
      where,
      order: { pingCangTime: 'DESC' },
    });
    const list = arr.map((item: any) => ({
      ...item,
      contractInfo: JSON.parse(item?.contractInfo),
      leverInfo: JSON.parse(item?.leverInfo),
      ysxYingKui: JSON.parse(item?.ysxYingKui),
    }));
    // 然后再查芝麻的历史仓位（从同步时间（或注册时间）到当前）
    // 2.是否查询芝麻历史仓位
    const timeInfo = getZhiMaPositionParams(userData);
    const bigTime = getBigTime(_endTime, timeInfo?.startTime);
    let zhimaPositions = [];
    if (!justMyData && bigTime === _endTime) {
      zhimaPositions = (await this.historyPositions(timeInfo))?.data;
    }
    const zhiMaTotal = zhimaPositions?.length;
    const _list = [...zhimaPositions, ...list].map((item: any, i: number) => {
      item.index = i + 1;
      // 处理做多做空方向
      item.newSide = handelLSCWDirection({ side: item?.side, userDirection: item?.userDirection });
      return item;
    });
    // 计算总盈亏
    const zongYingKui = countHPositionSY(_list);
    return formatSuccess({
      list: _list,
      total: _list.length,
      zhiMaTotal,
      heiDongTotal: list.length,
      zongYingKui: zongYingKui,
    });
  }

  // 删除历史仓位,默认删除所有
  async delAllLiShiPosition(list: any = null) {
    let datas = list;
    if (!list) datas = await this.positionRepository.find();
    const ids = datas.map(({ id }) => +id);
    await this.positionRepository.delete(ids);
    return formatSuccess(true);
    // const positions = await this.positionRepository.find();
    // const arr = positions.map(({ id }) => this.positionRepository.delete({ id }));
    // const res = await Promise.allSettled(arr);
    // const success = res.every((item) => item.status === 'fulfilled');
    // return success ? formatSuccess({ success }) : formatError({ msg: '删除失败' });
  }

  // 删除指定时间段的历史仓位
  async delLiShiPosition({ startTime }) {
    const endTime = dayjs().format('YYYY-MM-DD');
    // 1. 获取所有人(启用的)
    const users = (await this.userService.findAll({ is_active: 1, pageSize: 1000 }))?.data?.list.filter((item) => item?.zhima);
    // const userIds = users.map((item) => item?.id + '');
    const userIds = ['5', '9'];
    // 1. 获取历史仓位
    const positionApi = userIds.map((id) => this.myHistoryPosition(getDeleteDataParams(id, startTime)));
    const positionRes = await getBatchData({ api: positionApi, userIds });
    // 2. 获取同步数据
    const tongBuApi = userIds.map((id) => this.tongBuPositionService.findAll({ yuanGongId: +id, startTime, endTime }));
    const tongBuRes: any = await getBatchData({ api: tongBuApi, userIds });
    // 3. 获取历史委托
    const weiTuoApi = userIds.map((id) => this.orderService.myHistoryOrder(getDeleteDataParams(id, startTime)));
    const weiTuoRes: any = await getBatchData({ api: weiTuoApi, userIds });
    // 4. 获取成交记录
    const chengJiaoApi = userIds.map((id) => this.orderService.myTradesNew(getDeleteDataParams(id, startTime)));
    const chengJiaoRes: any = await getBatchData({ api: chengJiaoApi, userIds });
    // 5. 删除历史仓位,同步数据,历史委托, 成交记录
    // await this.delAllLiShiPosition(positionRes?.allList?.map((item) => ({ id: item?.id })));
    // await this.tongBuPositionService.deleteAll(tongBuRes?.allList?.map((item) => ({ id: item?.id })));
    // await this.orderService.delWeiTuos(weiTuoRes?.allList?.map((item) => ({ id: item?.id })));
    // await this.orderService.delChengJiaos(chengJiaoRes?.allList?.map((item) => ({ id: item?.id })));

    return formatSuccess({
      positionYuanShi: positionRes.yuanShi,
      positionAll: positionRes.allList,
      weiTuoYuanShi: weiTuoRes.yuanShi,
      weiTuoAll: weiTuoRes.allList,
      chengJiaoYuanShi: chengJiaoRes.yuanShi,
      chengJiaoAll: chengJiaoRes.allList,
      tongBuYuanShi: tongBuRes.yuanShi,
      tongBuAll: tongBuRes.allList,
    });
  }

  // 重置用户的芝麻盈亏、同步时间
  async resetUserYingKui({ startTime, endTime }) {
    console.log('重置用户的芝麻盈亏、同步时间');
    // 1. 获取所有人(启用的)
    const users = (await this.userService.findAll({ is_active: 1, pageSize: 1000 }))?.data?.list.filter((item) => item?.zhima);
    const userIds = users.map((item) => item?.id + '');
    // const userIds = ['5', '9'];
    // 2. 获取同步数据
    const tongBuApi = userIds.map((id) => this.tongBuPositionService.findAll({ yuanGongId: +id, startTime, endTime }));
    const tongBuRes: any = await getBatchData({ api: tongBuApi, userIds });
    const tongBuYuanShi = tongBuRes.yuanShi;
    const userMoneyMap = {};
    // yingKuiAll ,tongBuTime
    for (const key in tongBuYuanShi) {
      console.log('key: ', key);
      const fobj = tongBuYuanShi[key]?.[0];
      userMoneyMap[key] = { money: fobj?.yingKuiAll, tongBuTime: fobj?.tongBuTime };
    }

    // tongBuYuanShi
    return formatSuccess({
      tongBuYuanShi,
      userMoneyMap,
      users,
    });
  }

  // 重置同步信息: 删除所有的记录,历史仓位,用户同步记录
  async resetSyncData() {
    // 1.删除所有的记录
    await this.tongBuPositionService.deleteAll();
    // 2. 删除历史仓位
    await this.delAllLiShiPosition();
    // 3. 重置用户同步记录
    const users = (await this.userService.findAll({}))?.data?.list?.filter((item) => item?.zhima);
    const userParamsList = users.map((item) => ({
      id: item.id,
      yingKui: '0',
      tongBuTime: '0',
    }));
    await Promise.allSettled(userParamsList.map((item) => this.userService.edit(item)));
    return formatSuccess({
      userParamsList,
    });
  }

  // 自动爆仓
  async autoBaoCang() {
    const BaoCangMoney = 10; // 爆仓标准
    // 1. 获取所有人(启用的)
    const users = (await this.userService.findAll({ is_active: 1, pageSize: 1000 }))?.data?.list.filter((item) => item?.zhima);
    // 2. 获取所有人的可用余额
    const keYongRes: any = await Promise.allSettled(users.map((item) => this.userService.keYongMoney({ id: item.id + '', isNew: true })));
    const allList = users.map((item, i) => {
      const { id, name } = item;
      const keYongData = keYongRes[i]?.value?.data;
      const keYongMoney = keYongData?.keYongMoney?.toFixed(2);
      const currentPosition = keYongData?.positions;
      return { id, name, keYongMoney, userData: item, keYongData, currentPosition };
    });
    // 3. 筛选到爆仓标准的用户
    const baoCangUser = allList.filter(({ keYongMoney, currentPosition }) => Number(keYongMoney) < BaoCangMoney && currentPosition?.length > 0);
    // 测试爆仓-id=5
    // const baoCangUser = allList.filter((item) => item?.id === 5);
    // console.log('baoCangUser: ', baoCangUser);
    // 测试爆仓-id=5-结束
    const baoCangList = [];
    baoCangUser.map((item) => {
      const { key, secret } = item?.userData?.zhima;
      item.currentPosition?.map((position) => {
        baoCangList.push({ ...position, zhima: { key, secret } });
      });
    });
    // 4. 爆仓
    let baoCangRes: any = null;
    let baoCangParams = [];
    if (baoCangList.length > 0) {
      baoCangParams = getBaoCangParams(baoCangList);
      // 下单爆仓
      baoCangRes = await Promise.allSettled(baoCangParams.map(({ zhima, ...p }) => this.orderService.nodeAutoBaoCang({ e: p, zhima })));
    }
    return formatSuccess({
      allList,
      baoCangUser,
      baoCangList,
      baoCangParams,
      baoCangRes,
    });
  }

  // 一键平仓
  async yiJianPingCang() {
    console.log('一键平仓');
    // 1. 获取所有人(启用的)
    const users = (await this.userService.findAll({ is_active: 1, pageSize: 1000 }))?.data?.list.filter((item) => item?.zhima);
    // 2. 获取所有人的可用余额
    const keYongRes: any = await Promise.allSettled(users.map((item) => this.userService.keYongMoney({ id: item.id + '', isNew: true })));
    const allList = users.map((item, i) => {
      const { id, name } = item;
      const keYongData = keYongRes[i]?.value?.data;
      const currentPosition = keYongData?.positions;
      return { id, name, userData: item, currentPosition };
    });
    const baoCangUser = allList.filter(({ currentPosition }) => currentPosition?.length > 0);
    console.log('baoCangUser: ', baoCangUser);
    // 测试爆仓-id=5
    // const baoCangUser = allList.filter((item) => item?.id === 5);
    // console.log('baoCangUser: ', baoCangUser);
    // 测试爆仓-id=5-结束
    const baoCangList = [];
    baoCangUser.map((item) => {
      const { key, secret } = item?.userData?.zhima;
      item.currentPosition?.map((position) => {
        baoCangList.push({ ...position, zhima: { key, secret } });
      });
    });
    // 4. 一键平仓
    let baoCangRes: any = null;
    let baoCangParams = [];
    if (baoCangList.length > 0) {
      baoCangParams = getBaoCangParams(baoCangList, false);
      // 下单一键平仓
      baoCangRes = await Promise.allSettled(baoCangParams.map(({ zhima, ...p }) => this.orderService.nodeAutoBaoCang({ e: p, zhima })));
    }
    return formatSuccess({
      allList,
      baoCangUser,
      baoCangList,
      baoCangParams,
      baoCangRes,
      res: baoCangRes ? true : false,
    });
  }
}
